using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;

namespace ApiScanner.Core
{
    public abstract class ConfigurationElementCollection<T, TKey> : ConfigurationElementCollection, IEnumerable<T>, ICollection<T>
		 where T : ConfigurationElement, new()
	{
		protected sealed override object GetElementKey(ConfigurationElement element)
		{
			return GetElementKey((T) element);
		}

		protected abstract object GetElementKey(T element);

		protected override ConfigurationElement CreateNewElement()
		{
			return new T();
		}


        public bool Contains(T item)
        {
            return BaseIndexOf(item) != -1;
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public bool Contains(TKey key)
		{
			return Contains(key, EqualityComparer<TKey>.Default);
		}

		public bool Contains(TKey key, IEqualityComparer<TKey> comparer)
		{
			if (comparer == null) throw new ArgumentNullException("comparer");
			T result;

			return TryGet(key, comparer, out result);
		}

		public void Clear()
		{
			BaseClear();
		}

		public void RemoveAll(IEnumerable<T> items)
		{
			if (items == null) throw new ArgumentNullException("items");
			foreach (T entry in items)
			{
				Remove(entry);
			}
		}

		public void AddRange(IEnumerable<T> items)
		{
			if (items == null) throw new ArgumentNullException("items");


			foreach (T item in items)
			{
				Add(item);
			}
		}

		public void Add(T element)
		{
			if (element == null) throw new ArgumentNullException("element");

			BaseAdd(element, true);
		}

		public bool Remove(T element)
		{
			if (element == null) throw new ArgumentNullException("element");
			BaseRemove(GetElementKey(element));
		    return true;
		}

        public bool IsReadOnly
        {
            get { return false; }
        }

        public T this[int index]
		{
			get
			{
				return (T)BaseGetKey(index);
			}
		}

		public bool TryGet(TKey key, out T result)
		{
			return TryGet(key, EqualityComparer<TKey>.Default, out result);
		}

		public bool TryGet(TKey key, IEqualityComparer<TKey> comparer, out T result)
		{
			if (comparer == null) throw new ArgumentNullException("comparer");

			result = (from item in this
						 where comparer.Equals((TKey)GetElementKey(item), key)
						 select item).FirstOrDefault();
			return result != null;
		}

		public void Remove(TKey key)
		{
			Remove(key, EqualityComparer<TKey>.Default);
		}

		public void Remove(TKey key, IEqualityComparer<TKey> comparer)
		{
			if (comparer == null) throw new ArgumentNullException("comparer");
			T item;

			if (TryGet(key, comparer, out item))
			{
				Remove(item);
			}
		}

		IEnumerator<T> IEnumerable<T>.GetEnumerator()
		{
			foreach (T item in this)
			{
				yield return item;
			}
		}
	}
}